from django.contrib.auth.models import User
from django.core.serializers import get_serializer
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet
from rest_framework_extensions.cache.mixins import CacheResponseMixin

from .models import Area, Address
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from rest_framework import viewsets, serializers, status
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework_simplejwt.views import TokenObtainPairView
from users.serializers import UserSerializer, MyTokenTokenObtainPairSerializer, UserDetailSerializer, \
    UpdatePasswordSerializer, AreaSerializer, ParentAreaSerializer, AddressSerializer
from rest_framework.permissions import IsAuthenticated
from utils.verifyUtil import VerifyUtil
import io
# Create your views here.
from django_redis import get_redis_connection
from jt32.settings import CACHES
from  config.dbs.redisConfig import KEY_TEMPLATE,EXPIRE_TIME
# 导入 fastdfs
from fdfs_client.client import Fdfs_client,get_tracker_conf
#根据配置信息得到 连接信息地址 连接fastdfs
client = get_tracker_conf("fastdfs/client.conf")
# 得到客户端对象
client = Fdfs_client(client)
import logging
# 得到日志对象
logger = logging.getLogger(__name__)


# 验证码的视图
# 验证码不需要增删改查




class ImageVerifyView(View):
    # 127.0.0.1:8000/user/verification  ==>get
    # 127.0.0.1:8000/user/verification/register/uuid  ==>get
    # 127.0.0.1:8000/user/verification/login/uuid  ==>get
    def get(self, request,func,uuid):
        """

        :param request:
        :param func: func==login   func== register
        :param uuid:
        :return:
        """
        imgverifyUtil = VerifyUtil() # 验证码实例对象
        img, code = imgverifyUtil.verify_code() # 图片数据   验证码数据
        # 生成验证码图片 图片不需要永久存储
        # 请求接口的时候生成图片  ==》 字节流  ==》 保存在内存中  （临时文件）
        img_bytes = io.BytesIO() # 生成临时字节文件
        # 吧图片存储到 img_bytes 字节文件中  指定png格式
        img.save(img_bytes,'PNG')
        # 吧png字节文件数据 读取返回出去
        img_bytes = img_bytes.getvalue()

        # 存储一份redis 里面
        # 吧redis连接信息 作为参数  ==》redis缓存对象
        cache = get_redis_connection(alias='verify_codes')
        # 吧验证码存入
        # set(key:value)
        cache.set(KEY_TEMPLATE % (func,uuid),code,EXPIRE_TIME)
        # 返回响应到前端的时候  ==》 字节数据
        return HttpResponse(img_bytes, content_type='image/png')



# 用户的操作
# 需要有增删改查 ModelViewSet
class UserViewSet(viewsets.GenericViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    # 重写权限的分配
    def get_permissions(self):
        if self.action in ["now","info"]:
            # IsAuthenticated 检验用户是否登录
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = []

        return [permission() for permission in permission_classes]

    # 重写序列器方法
    def get_serializer_class(self):
        if self.action == "info":
            return UserDetailSerializer # self.get_serializer()==>UserDetailSerializer
        elif self.action == "password":
            return UpdatePasswordSerializer
        else:
            return UserSerializer  # self.get_serializer()==> UserSerializer

    # 重新一些create方法
    def create(self, request, *args, **kwargs):

        # 获取前端数据 json
        # 反序列化
        serializer = self.get_serializer(data=request.data) # 创建操作
        serializer.is_valid(raise_exception=True)
        # 获取用户名
        username = request.data.get('username')
        # 获取密码
        password = request.data.get('password')
        # 存储
        user = User(username=username)
        # 需要密码加密 set_password() 加密操作
        user.set_password(password)
        user.save()
        # 返回数据 json格式数据
        return Response(serializer.data)


    # 自定义now方法  展示用户信息
    @action(methods=['get'], detail=False) # 不需要传id  默认当前的登录用户
    def now(self,request):
        # 序列化
        serializer = self.get_serializer(request.user)
        return Response(serializer.data)

    # 用户详情的增改
    @action(methods=['put'], detail=False) # 不需要传id  默认当前的登录用户
    def info(self,request):
        logger.info("12123")
        # 获取用户数据
        user = request.user
        # 安全机制
        request.POST._mutable = True # 允许修改post传入的参数  1     2
        request.data["user"] = user.id

        # 获取头像
        file = request.FILES.get('file')
        # 判断有没有数据
        if file:
            # 判断是不是图片数据
            if file.content_type not in ["image/png","image/jpeg"]:
                # 不是图片报错异常
                return  Response({"detail":"仅支持png或者jpg的格式"},status=status.HTTP_400_BAD_REQUEST)

            # 获取文件后缀  xxx.png  xxx.jpg
            try:
                image_ext_name = file.name.split('.')[-1]
            except Exception as e:
                logger.info(f"图片扩展名异常 {e}")
                image_ext_name = "png"

            # 上传到fastdfs
            try:
                upload_res = client.upload_by_buffer(file.read(),file_ext_name=image_ext_name)

            except Exception as e:
                logger.error(f"图片上传异常{e}" )
                return Response({"detail": "图片上传错误"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            # 判断是否成功
            if upload_res.get("Status") != "Upload successed.":
                logger.error(f"图片上传失败{e}")
                return Response({"detail": "图片上传失败"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


            # 判断是否已经存在头像
            if hasattr(user, "userdetail") and user.userdetail.avatar:
                # 替换
                #  删除之前的头像信息  数据库里面的头像不需要更新
                # storage容器里面的头像  encode() 编码 吧字符数据 转成 二进制数据
                try:
                    client.delete_file(user.userdetail.avatar.encode())
                except Exception as e:
                    logger.error(f"头像删除失败{e}")

            # 得到新头像的地址                       decode() 解码成字符数据
            image_url = upload_res.get("Remote file_id").decode()


            request.data["avatar"] = image_url




        # 是否存在用户详情
        # 一对一正反向关联  模型名
        if hasattr(user,"userdetail"):
            # 修改操作
            # 前端传入的数据  request.data
            user_detail_serializer = self.get_serializer(instance=user.userdetail, data=request.data)
        else:
            # 创建用户详情操作
            user_detail_serializer = self.get_serializer(data=request.data)
        user_detail_serializer.is_valid(raise_exception=True)
        user_detail_serializer.save()
        # 返回序列化后的数据
        return Response(user_detail_serializer.data)

        # 数据反序列化是用  UserDetailSerializer

    # 修改密码
    @action(methods=['put'], detail=False)  # 不需要传id  默认当前的登录用户
    def password(self,request):
        # 获取当前的用户信息
        user = request.user
        # 校验是否通过
        # request.data
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 持久化保存
        # password  = serializer.data.get('password')
        # 获取新密码
        new_password = serializer.data.get('new_password')
        user.set_password(new_password)
        user.save()
        return Response({"msg":"密码修改成功"})
        # print(new_password)
        # if user.check_password(password):
        #     # 进行密码加密
        #     user.set_password(new_password)
        #     user.save()
        #     return Response({"msg":"密码修改成功"})
        # else:
        #     return Response(status=status.HTTP_400_BAD_REQUEST)


# 登录认证
class MyTokenTokenObtainPairView(TokenObtainPairView):
    # 指定序列化器
    serializer_class = MyTokenTokenObtainPairSerializer



# 地区的视图
class AreaViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
    # CacheResponseMixin===>BaseCacheResponseMixin==>extensions_api_settings==>settings==>REST_FRAMEWORK_EXTENSIONS
    queryset = Area.objects.all()
    serializer_class = AreaSerializer
    permission_classes = [IsAuthenticated]

    # 重写查询集
    def get_queryset(self):
        if self.action in ["list"]: # 一级行政区域
            return Area.objects.filter(parent__isnull=True)
        else:
            return self.queryset

    def get_serializer_class(self):
        if self.action in ["list"]:
            return AreaSerializer
        else:
            return ParentAreaSerializer


# 收货地址视图
class AddressViewSet(ModelViewSet):
    # 收货地址的数据
    queryset = Address.objects.filter(is_delete=False)
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # 当前用户的收货地址数据  user.address_set
        # print(self.request.user)
        # print(type(self.request.user))
        return self.request.user.address_set.filter(is_delete=False)
        # return User.objects.filter(is_superuser=False).first().address_set.filter(is_delete=False)
        # no_admin_users = User.objects.filter(is_superuser=False)
        # return Address.objects.filter(user__in=no_admin_users).filter(is_delete=False)

    # 重写create方法
    def create(self, request, *args, **kwargs):

        request.POST._mutable = True
        request.data["user"] = request.user.id
        # 判断收货地址的个数
        if self.get_queryset().filter(is_delete=False).count() >= 5:
            return Response({
                "detail":"您的收货地址已达到5个，请删除多余的收货地址"
            },status=status.HTTP_400_BAD_REQUEST)

        return ModelViewSet.create(self, request, *args, **kwargs)